package se.webbzon.boltzmann.minigame.effect;

import se.webbzon.boltzmann.minigame.sandbox.DefaultSandBoxItem;
import se.webbzon.boltzmann.minigame.sandbox.SandBox;
import se.webbzon.boltzmann.minigame.sandbox.SandBoxIcon;
import se.webbzon.boltzmann.minigame.sandbox.SandBoxItem;
import se.webbzon.boltzmann.minigame.sandbox.SandBoxObject;
import se.webbzon.boltzmann.resource.Resources;
import se.webbzon.oschi01.resourceset.ResourceSet;
import se.webbzon.oschi01.textureset.Texture3D;
import se.webbzon.oschi01.worldarea.WorldArea;
import se.webbzon.oschi01.worldcamera.WorldCameraPane;
import se.webbzon.oschi01.worldobject.WorldObject;

public class SandBoxCloud extends DefaultSandBoxItem {
	
	// The 2-dimensional depth of the rain
	private static final int depth = 150;
	
	// The default intensity
	private static final double defaultIntensity = 1;
	
	// The time between cloud phases
	private static final int phaseTime = 20;
	
	// The size of the spread and the cloud
	private static final int defaultWidth = 128, defaultHeight = 32;
	private static final int cloudWidth = 128, cloudHeight = 128;
	
	// The intensity of the cloud
	private double intensity;
	
	// The texture set of the rain
	private final ResourceSet<Texture3D> textureSet;
	
	// The sand box to which this rain is attached
	private SandBox box;
	
	/*============================================================
	Constructors
	============================================================*/
	
	public SandBoxCloud() {
		textureSet = Resources.getTextureSet("weather_cloud");
		intensity = defaultIntensity;
		setInstance(new CloudGenerator());
		setSize(defaultWidth,defaultHeight);
	}
	
	/*============================================================
	Public Methods
	============================================================*/
	
	@Override public void setSize(double width, double height) {
		super.setSize(width, height);
	}
	
	/** Returns the intensity of the cloud. **/
	public double getIntensity() {
		return intensity;
	}
	
	/** Sets the intensity of the cloud. **/
	public void setIntensity(double intensity) {
		this.intensity = intensity;
	}
	
	/*============================================================
	Private Classes
	============================================================*/
	
	private final class CloudGenerator extends SandBoxObject {
		
		private double regen;

		public CloudGenerator() {
			super(WorldObject.onStep, 0);
			regen = 0;
		}

		@Override public void onAttach(SandBox box) {
			SandBoxCloud.this.box = box;
		}

		@Override public void onDetach(SandBox box) {
			SandBoxCloud.this.box = null;
		}

		@Override public SandBoxIcon createIcon() {
			return null;
		}

		@Override public void onStep(WorldArea world) {
			if (regen >= 1) {
				int clouds = (int) regen;
				for (int i = 0; i < clouds; i++) {
					int imageIndex = (int) (Math.random() * textureSet.size());
					Cloud cloud = new Cloud(imageIndex);
					double x = getX() + getWidth() * (- 0.5 + Math.random());
					double y = getY() + getHeight() * (- 0.5 + Math.random());
					cloud.setPosition(x, y);
					box.addItem(cloud);
				}
				regen -= clouds;
			} else
				regen += intensity;
		}
		
	}
	
	private final class Cloud extends WorldObject implements SandBoxItem {
		
		private double x, y;
		
		private int imageIndex, phase, remaining;
		
		public Cloud(int imageIndex) {
			super(WorldObject.onStep + WorldObject.onPostDraw, depth);
			this.imageIndex = imageIndex;
			remaining = phaseTime;
			phase = 0;
		}

		@Override public void onAttach(SandBox box) {
			box.getWorld().createInstance(this);
		}

		@Override public void onDetach(SandBox box) {
			box.getWorld().destroyInstance(this);
		}

		@Override public SandBoxIcon createIcon() {
			return null;
		}

		@Override public void onStep(WorldArea world) {
			if (remaining == 0) {
				if (phase < 2) {
					phase++;
					remaining = phaseTime;
				} else if (box == null)
					world.destroyInstance(this);
				else
					box.removeItem(this);
			} else {
				remaining--;
			}
		}
		
		@Override public void onPostDraw(WorldArea world, WorldCameraPane hud) {
			if (phase == 0) {
				float alpha = 1 - remaining / (float) phaseTime;
				hud.setTransparency(alpha);
			} else if (phase == 2) {
				float alpha = remaining / (float) phaseTime;
				hud.setTransparency(alpha);
			}
			int w = (int) getWidth();
			int h = (int) getHeight();
			int x = (int) this.x - w/2;
			int y = (int) this.y - h/2;
			hud.drawImage(textureSet.get(imageIndex).getImage(), x, y, w, h);
			if (phase != 1)
				hud.setTransparency(1);
		}

		@Override public boolean draggable() {
			return false;
		}

		@Override public boolean droppable() {
			return false;
		}

		@Override public void setPosition(double x, double y) {
			this.x = x;
			this.y = y;
		}

		@Override public double getX() {
			return x;
		}

		@Override public double getY() {
			return y;
		}

		@Override public double getWidth() {
			return cloudWidth;
		}

		@Override public double getHeight() {
			return cloudHeight;
		}
		
	}

}
